#include "load_img.h"

uint8_t pc_reg [0x8000000];
FILE *log_fp = NULL;
extern char *img_file;
/// /////////////////////////////
//// FUNCTION  load_img 读取二进制文件
//////////////////////////////////
long load_img() {
  if (img_file == NULL) {
    printf("No image is given. Use the default build-in image.\n");
    return 4096; // built-in image size
  }
  FILE *fp = fopen(img_file, "rb");
  printf("image = %s",img_file);
  if (fp==NULL)
  {
	return 0;
  }
  fseek(fp, 0, SEEK_END);//设置流 stream 的文件位置为给定的偏移 offset，参数 offset 意味着从给定的 whence（从何处; 从哪里;） 位置查找的字节数。
  long size = ftell(fp);//ftell用于获取文件位置指针当前位置相对于文件首的偏移字节数。
  printf(ANSI_FG_BLUE "The image is %s, size = %ld\n" ANSI_NONE, img_file, size);
  fseek(fp, 0, SEEK_SET);
  int ret = fread(&pc_reg, size, 1, fp);
//   for (size_t i = 0; i < 10; i++)
//   {
//     printf("pc_reg[%d]=%x\n",i,pc_reg[i]);
//   }
  
  assert(ret == 1);
  fclose(fp);
  return size;
}
/// /////////////////////////////
//////////////////////////////////


/// /////////////////////////////
//// FUNCTION  init_log 初始化log文件
//////////////////////////////////
void init_log(const char *log_file) {
  log_fp = stdout;
  if (log_file != NULL) {
    FILE *fp = fopen(log_file, "w");
    log_fp = fp;
  }
}
/// /////////////////////////////
//////////////////////////////////




#ifdef FTRACE
/// /////////////////////////////
//// elf文件解析部分
//////////////////////////////////
typedef struct func {
  uint64_t start;
  uint64_t size;
  uint64_t end;
  struct func *next;
  char  name [100];
} FC;
FC *func_w = NULL;
FC *fc_head=NULL;
FC  fc_pool [100] = {};
char func_ [9][32];
/// /////////////////////////////
//// FUNCTION  init_fc_pool
//////////////////////////////////
void init_fc_pool() {
    int i;
    for (i = 0; i < 32; i ++) {
        fc_pool[i].start = 0;
        fc_pool[i].size = 0;
        fc_pool[i].end = 0;
        fc_pool[i].next = (i == 32 - 1 ? NULL : &fc_pool[i + 1]);
    }
    func_w = fc_pool;
    fc_head = NULL;
}

/// /////////////////////////////
//// FUNCTION  write_wp 
//////////////////////////////////
void write_wp(uint64_t start,uint64_t size,uint64_t end,char * func_name){
    FC *p=NULL;
    FC *n=NULL;
    p = fc_head;
    n = func_w;
    func_w = func_w->next;
    n->start = start;
    n->size = size;
    n->end = end;
    n->next = NULL;
    memcpy(n->name,func_name,strlen(func_name)+1);    
    if(p ==NULL){
        fc_head = n;
        p = fc_head;
    }
    else{
        while (p->next)
        {
        p = p->next;
        }
        p->next = n;
    }
};
/// /////////////////////////////
//// FUNCTION  add_elf 
//////////////////////////////////
void add_elf(char * file){
    int fd;
    uint8_t *mem;
    uint64_t sym_num = 0;
    struct stat st;
    Elf64_Ehdr *ehdr; /* ELF头 */
    Elf64_Shdr *shdr; /* 节头 */
    Elf64_Sym  *sym = NULL;  /* 符号 */
    unsigned char *sht_symtab= NULL, *temp1= NULL,*temp2 = NULL;///*sht_strtab,
    u_int16_t  section_num;
    size_t  symtab_num=0;//,shstr_num,str_num;
    init_fc_pool();
    fd = open(file,O_RDONLY);
    if (fstat(fd, &st) < 0) {
        perror("fstat");
        exit(-1);
    }
    /* 映射可执行文件 */
    mem = (uint8_t *)mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (mem == NULL) {
        perror("mmap");
        exit(-1);
    }
    /* ELF文件头起始于文件的0偏移 */
    ehdr = (Elf64_Ehdr *) mem;

    shdr = (Elf64_Shdr *) &mem[ehdr->e_shoff];
    section_num = ehdr->e_shnum;
    for (size_t i = 0; i < section_num; i++)
    {
        if (shdr[i].sh_type==SHT_SYMTAB)
        {
            sht_symtab = &mem[shdr[i].sh_offset];
            sym_num    = shdr[i].sh_size / shdr[i].sh_entsize;
            sym = (Elf64_Sym *) sht_symtab;
            symtab_num = i;
        }
    }
    for (size_t i = 0; i < section_num; i++)
    {
        if (shdr[i].sh_type==SHT_STRTAB )
        {
            temp1 =  &mem[shdr[i].sh_offset];
            if(!strcmp((char *)&temp1[shdr[symtab_num].sh_name], ".symtab")){
                break;
            }
        }
    } 
    for (size_t i = 0; i < section_num; i++)
    {
        if(!strcmp((char *)&temp1[shdr[i].sh_name], ".strtab")){
            temp2 =  &mem[shdr[i].sh_offset];
        }
    } 
    char fun_name[64];
    for (size_t i = 0; i < sym_num; i++)
    {
        if (sym[i].st_info%4 == STT_FUNC && sym[i].st_size)
        {
            sprintf(fun_name,"%s",&temp2[sym[i].st_name]);
            write_wp(sym[i].st_value,sym[i].st_size,sym[i].st_value+sym[i].st_size-4,fun_name);
        }
    }
    FC *p=fc_head;
#ifdef DISPLAY
    while (p)
    {
      printf("0x%lx,0x%lx,0x%lx,%s\n",p->start,p->size,p->end,p->name);
      p=p->next;
    } 
#endif
}
#endif
////////////////////////////////
////////////////////////////////